package com.cruise.game.service.impl.user;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cruise.game.common.api.ApiException;
import com.cruise.game.common.enums.RoleEnum;
import com.cruise.game.mapper.AgentApplicationMapper;
import com.cruise.game.mapper.TransactionMapper;
import com.cruise.game.mapper.UserMapper;
import com.cruise.game.mapper.WithdrawalApplicationMapper;
import com.cruise.game.model.entity.AgentApplication;
import com.cruise.game.model.entity.Transaction;
import com.cruise.game.model.entity.User;
import com.cruise.game.model.entity.WithdrawalApplication;
import com.cruise.game.model.param.user.AgentApplicationParam;
import com.cruise.game.model.param.user.RechargeParam;
import com.cruise.game.model.param.user.UpdateProfileParam;
import com.cruise.game.model.param.user.WithdrawParam;
import com.cruise.game.model.vo.common.PageResult;
import com.cruise.game.model.vo.user.TransactionVO;
import com.cruise.game.model.vo.user.UserProfileVO;
import com.cruise.game.model.vo.user.WithdrawalVO;
import com.cruise.game.service.user.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 用户服务实现
 * 
 * @author cruise
 * @date 2025-02-28
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private AgentApplicationMapper agentApplicationMapper;

    @Resource
    private TransactionMapper transactionMapper;

    @Resource
    private WithdrawalApplicationMapper withdrawalApplicationMapper;

    @Value("${wx.miniapp.appid}")
    private String appid;

    @Override
    public UserProfileVO getUserProfile(Long userId) {
        // 查询用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new ApiException("用户不存在");
        }

        // 构建用户个人信息VO
        UserProfileVO profileVO = new UserProfileVO();
        profileVO.setId(user.getId());
        profileVO.setNickname(user.getNickname());
        profileVO.setAvatar(user.getAvatarUrl());
        profileVO.setPhone(user.getPhone());
        profileVO.setWechatId(user.getWechatId());
        profileVO.setBalance(user.getBalance());
        profileVO.setRole(user.getRole());

        return profileVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserProfileVO updateUserProfile(Long userId, UpdateProfileParam param) {
        // 查询用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new ApiException("用户不存在");
        }

        // 更新用户信息
        if (StringUtils.isNotBlank(param.getNickname())) {
            user.setNickname(param.getNickname());
        }
        if (StringUtils.isNotBlank(param.getAvatar())) {
            user.setAvatarUrl(param.getAvatar());
        }
        if (StringUtils.isNotBlank(param.getPhone())) {
            user.setPhone(param.getPhone());
        }
        if (StringUtils.isNotBlank(param.getWechatId())) {
            user.setWechatId(param.getWechatId());
        }

        // 设置更新时间
        user.setUpdatedAt(LocalDateTime.now());

        // 更新用户
        userMapper.updateById(user);

        // 返回更新后的用户个人信息
        return getUserProfile(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long applyAgent(Long userId, AgentApplicationParam param) {
        // 查询用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new ApiException("用户不存在");
        }

        // 验证用户角色
        if (RoleEnum.isAgent(user.getRole()) || RoleEnum.isAdmin(user.getRole())) {
            throw new ApiException("已经是代理或管理员，无需申请");
        }

        // 验证是否已有未处理的申请
        LambdaQueryWrapper<AgentApplication> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AgentApplication::getUserId, userId);
        queryWrapper.eq(AgentApplication::getStatus, "pending");
        Integer count = agentApplicationMapper.selectCount(queryWrapper).intValue();
        if (count != null && count > 0) {
            throw new ApiException("已有待处理的申请，请等待审核");
        }

        // 构建打手申请对象
        AgentApplication application = new AgentApplication();
        application.setUserId(userId);
        application.setGameCategoryId(param.getGameCategoryId());
        application.setServicePrice(param.getServicePrice());
        application.setDescription(param.getDescription());
        application.setContactInfo(param.getContactInfo());
        application.setStatus("pending");

        // 设置时间
        LocalDateTime now = LocalDateTime.now();
        application.setCreatedAt(now);
        application.setUpdatedAt(now);

        // 保存申请
        agentApplicationMapper.insert(application);

        return application.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PaymentInfoVO recharge(Long userId, RechargeParam param) {
        // 查询用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new ApiException("用户不存在");
        }

        // 创建交易记录
        Transaction transaction = new Transaction();
        transaction.setUserId(userId);
        transaction.setAmount(param.getAmount());
        transaction.setType("recharge");
        transaction.setStatus("pending");

        // 设置时间
        LocalDateTime now = LocalDateTime.now();
        transaction.setCreatedAt(now);
        transaction.setUpdatedAt(now);

        // 保存交易记录
        transactionMapper.insert(transaction);

        // TODO: 调用微信支付接口

        // 模拟支付信息
        String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
        String nonceStr = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 16);
        String packageValue = "prepay_id=wx" + timeStamp;
        String signType = "MD5";
        String paySign = "simulated_pay_sign";

        return new PaymentInfoVO(appid, timeStamp, nonceStr, packageValue, signType, paySign);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long withdraw(Long userId, WithdrawParam param) {
        // 查询用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new ApiException("用户不存在");
        }

        // 验证余额是否充足
        if (user.getBalance().compareTo(param.getAmount()) < 0) {
            throw new ApiException("余额不足");
        }

        // 创建提现申请
        WithdrawalApplication application = new WithdrawalApplication();
        application.setUserId(userId);
        application.setAmount(param.getAmount());
        application.setStatus("pending");
        application.setRemark(param.getRemark());

        // 设置时间
        LocalDateTime now = LocalDateTime.now();
        application.setCreatedAt(now);
        application.setUpdatedAt(now);

        // 保存提现申请
        withdrawalApplicationMapper.insert(application);

        // 扣减用户余额
        userMapper.updateBalance(userId, param.getAmount().negate());

        // 创建交易记录
        Transaction transaction = new Transaction();
        transaction.setUserId(userId);
        transaction.setAmount(param.getAmount());
        transaction.setType("withdrawal");
        transaction.setStatus("pending");
        transaction.setCreatedAt(now);
        transaction.setUpdatedAt(now);
        transactionMapper.insert(transaction);

        return application.getId();
    }

    @Override
    public PageResult<TransactionVO> getTransactions(Long userId, String type, Integer page, Integer pageSize) {
        // 计算偏移量
        int offset = (page - 1) * pageSize;

        // 使用自定义查询方法，避免双LIMIT问题
        List<Transaction> transactions = transactionMapper.getUserTransactions(userId, type, offset, pageSize);

        // 转换为VO
        List<TransactionVO> transactionVOs = transactions.stream()
                .map(transaction -> {
                    TransactionVO vo = new TransactionVO();
                    BeanUtils.copyProperties(transaction, vo);
                    return vo;
                })
                .collect(Collectors.toList());

        // 使用自定义方法计算总记录数
        Long total = transactionMapper.countUserTransactions(userId, type);

        // 返回分页结果
        return PageResult.of(transactionVOs, total, page, pageSize);
    }

    @Override
    public PageResult<WithdrawalVO> getWithdrawals(Long userId, String status, Integer page, Integer pageSize) {
        // 计算偏移量
        int offset = (page - 1) * pageSize;

        // 构建查询条件
        LambdaQueryWrapper<WithdrawalApplication> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WithdrawalApplication::getUserId, userId);
        if (StringUtils.isNotBlank(status)) {
            queryWrapper.eq(WithdrawalApplication::getStatus, status);
        }
        queryWrapper.orderByDesc(WithdrawalApplication::getCreatedAt);

        // 不使用last("LIMIT")，直接使用MyBatis-Plus的分页
        Page<WithdrawalApplication> pageParam = new Page<>(page, pageSize);
        Page<WithdrawalApplication> withdrawalPage = withdrawalApplicationMapper.selectPage(pageParam, queryWrapper);

        // 获取查询结果和总数
        List<WithdrawalApplication> withdrawals = withdrawalPage.getRecords();
        long total = withdrawalPage.getTotal();

        // 转换为VO
        List<WithdrawalVO> withdrawalVOs = withdrawals.stream()
                .map(withdrawal -> {
                    WithdrawalVO vo = new WithdrawalVO();
                    BeanUtils.copyProperties(withdrawal, vo);
                    return vo;
                })
                .collect(Collectors.toList());

        // 返回分页结果
        return PageResult.of(withdrawalVOs, total, page, pageSize);
    }
}
